home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 722 / 722.xpi / chrome / noscript.jar / content / noscript / ClearClickHandlerLegacy.js < prev    next >
Text File  |  2010-02-12  |  17KB  |  499 lines

  1.  
  2. (function() {
  3.   
  4.   var ClearClickHandlerLegacy = {  
  5.      // the following is apparently correct and easy, but it suffers of HUGE rounding issues
  6.     _getZoomFromBrowser: function(browser) {
  7.       try {
  8.         return this._zoom = browser.markupDocumentViewer && browser.markupDocumentViewer.fullZoom || 1;
  9.       } catch(e) {
  10.         return this._zoom;
  11.       }
  12.     },
  13.     
  14.     // this one is more complex but much more precise than getZoomForBrowser()
  15.     _getZoomFromDocument: function(d) {
  16.       
  17.       var root = d.documentElement;
  18.       var o = d.createElementNS(HTML_NS, "div");
  19.       var s = o.style;
  20.       s.top = "400000px";
  21.       s.position = "absolute";
  22.       s.display = "block";
  23.     
  24.       root.appendChild(o);
  25.       var oBox = d.getBoxObjectFor(o);
  26.       var rootBox = d.getBoxObjectFor(root);
  27.       var zoom = (oBox.screenY - rootBox.screenY) / o.offsetTop;
  28.       root.removeChild(o);
  29.       return this._zoom = zoom > 0 ? zoom : this._zoom;
  30.     },
  31.   
  32.     getBox: function(o, d, w) {
  33.       var zoom = this._zoom || 1;
  34.       if (!d) d = o.ownerDocument;
  35.       if (!w) w = d.defaultView;
  36.         
  37.       var b = d.getBoxObjectFor(o); // TODO: invent something when boxObject is missing or failing
  38.       var c = d.getBoxObjectFor(d.documentElement);
  39.       var p;
  40.       var r = {
  41.         width: b.width, height: b.height,
  42.         screenX: b.screenX, screenY: b.screenY
  43.       };
  44.       
  45.       const ns = this.ns;
  46.       var verbose = ns.consoleDump & LOG_CLEARCLICK;
  47.       
  48.       r.x = (r.screenX - c.screenX) / zoom;
  49.       r.y = (r.screenY - c.screenY) / zoom;
  50.       
  51.       var dx;
  52.       // here we do our best to improve on lousy boxObject horizontal behavior when line breaks are involved
  53.       // (it reports the width of the whole line, but x is referred to the first text node offset)
  54.       if ("getBoundingClientRect" in o) {
  55.         c = o.getBoundingClientRect(); // bounding rect, if available, does the right thing with left position
  56.         
  57.         if (verbose) ns.dump("Rect: " + c.left + "," + c.top + "," + c.right + "," + c.bottom);
  58.         
  59.         // boxObject.x "knows" scrolling, but on clientRect.left we must accumulate scrollX until first fixed object or viewport (documentElement)
  60.         var fixed, scrollX;
  61.         dx = Math.round(c.left) - r.x;
  62.         var s = w.getComputedStyle(o, '');
  63.         dx += parseInt(s.borderLeftWidth) || 0 + parseInt(s.paddingLeft) || 0 + w.scrollX;
  64.       
  65.       } else {
  66.         // ugly hack for line-breaks without boundClient API
  67.         dx = 0;
  68.         p = b.parentBox;
  69.         if (p) {
  70.           var pb = d.getBoxObjectFor(p);
  71.           if (verbose) dump("Parent: " + pb.x + "," + pb.y + "," + pb.width + "," + pb.height);
  72.           if (b.x + r.width - pb.x - pb.width >= r.width / 2) {
  73.             dx = -(b.x - (pb.width - r.width));
  74.           }
  75.         }
  76.       }
  77.       
  78.       
  79.       r.screenX += dx * zoom;
  80.       r.x += dx;
  81.       
  82.      
  83.       if (verbose) ns.dump(o + r.toSource() + " -- box: " + b.x + "," + b.y);
  84.       return r;
  85.     },
  86.     
  87.     
  88.     _constrain: function(box, axys, dim, max, vp, center, zoom) {
  89.       var d;
  90.       var scr = "screen" + axys.toUpperCase();
  91.       // trim bounds to take in account fancy overlay borders
  92.       var l = box[dim];
  93.       var n = box[axys];
  94.       
  95.       if (vp.frame && center && l < vp[dim]) { // expand to viewport if possible
  96.         l = vp[dim];
  97.       }
  98.       
  99.       if (l > 6) {
  100.         var bStart = Math.floor(l * .1) // 20% border
  101.         var bEnd = bStart;
  102.         if (bStart + n > center) {
  103.           bStart = center - n;
  104.         } else if (l + n - center < bEnd) {
  105.           bEnd = l + n - center;
  106.         } 
  107.         box[dim] = (l -= (bStart + bEnd));
  108.         box[axys] = (n += bStart);
  109.         box[scr] += bStart * zoom;
  110.         
  111.       }
  112.   
  113.       if (l > max) {
  114.         // resize
  115.         if (center) {
  116.           var halfMax = Math.round(max / 2);
  117.           var nn = center - halfMax;
  118.           if (nn > n && center + halfMax > n + l) nn = (n + l) - max;        
  119.           box[axys] = nn;
  120.           box[scr] += (nn - n) * zoom;
  121.           n = nn;
  122.         }
  123.         l = box[dim] = max;
  124.       }
  125.       // slide into viewport
  126.       var vpn = vp[axys];
  127.       d = (n < vpn)
  128.           ? vpn - n
  129.           : (n + l) > (vpn + vp[dim])
  130.             ? (vpn + vp[dim]) - (n + l)
  131.             : 0;
  132.       
  133.       if (d) {
  134.         n = (box[axys] += d);
  135.         box[scr] += d * zoom;
  136.       }
  137.   
  138.     },
  139.     
  140.     isSupported: function(doc) {
  141.       return "_supported" in this
  142.         ? this._supported
  143.         : this._supported = typeof(this.createCanvas(doc).toDataURL) == "function" &&
  144.           ("getBoxObjectFor" in doc);  
  145.     },
  146.     
  147.    
  148.     checkObstruction: function(o, ctx) {   
  149.       var d = o.ownerDocument;
  150.       var dElem = d.documentElement;
  151.       
  152.       var w = d.defaultView;
  153.       var top = w.top;
  154.       var browser = DOM.findBrowserForNode(top);
  155.       
  156.       var c = this.createCanvas(browser.ownerDocument);
  157.       var gfx = c.getContext("2d");
  158.       
  159.       var bg = this.getBG(w);
  160.   
  161.   
  162.       var bgStyle;
  163.       var box, curtain;
  164.       
  165.       var frame, frameClass, frameStyle, objClass, viewer;
  166.       
  167.       var docPatcher = new DocPatcher(this.ns, o, w);
  168.       
  169.       var sheet = null;
  170.       
  171.       var img1 = null, img2 = null, tmpImg = null;
  172.       
  173.       function snapshot(w, x, y) {
  174.         gfx.drawWindow(w, Math.round(x), Math.round(y), c.width, c.height, bg);
  175.         return c.toDataURL();
  176.       }
  177.       
  178.       function snapshots(x1, y1, x2, y2) {
  179.         img1 = null;
  180.         try {
  181.           if (objClass) docPatcher.clean(true);
  182.           img1 = snapshot(w, x1, y1);
  183.         } catch(ex) {
  184.           throw ex;
  185.         } finally {
  186.           docPatcher.clean(false);
  187.         }
  188.         img2 = tmpImg = snapshot(top, x2, y2);
  189.         return (img1 != img2); 
  190.       }
  191.       var sd = this._NO_SCROLLBARS;
  192.   
  193.       try {
  194.             
  195.         var zoom = this._getZoomFromBrowser(browser);
  196.         if (zoom != 1) zoom = this._getZoomFromDocument(d);
  197.         
  198.         docPatcher.linkAlertHack(true);
  199.         docPatcher.fbPresenceHack(true);
  200.         
  201.         try {
  202.           docPatcher.opaque(true);
  203.           
  204.           var fbPresence; // hack for Facebooks's fixed positioned widget
  205.           
  206.           if (ctx.isEmbed) { // objects and embeds
  207.             if (this.ns.getPref("clearClick.plugins", true)) {
  208.               var ds = browser.docShell;
  209.               viewer = ds.contentViewer && false;
  210.               objClass = new ClassyObj(o);
  211.               objClass.append(" __noscriptBlank__");
  212.               docPatcher.blankPositioned(true);
  213.               docPatcher.clean(true);
  214.             } else {
  215.               DOM.addClass(o, "__noscriptOpaqued__");
  216.             }
  217.           }
  218.           
  219.           if ((frame = w.frameElement)) {
  220.             frameClass = new ClassyObj(frame);
  221.             DOM.removeClass(frame, "__noscriptScrolling__");
  222.             sd = this.computeScrollbarSizes(frame, dElem, d.body);  
  223.           }
  224.           
  225.           var clientHeight = w.innerHeight - sd.h;
  226.           var clientWidth =  w.innerWidth - sd.w;
  227.           // print(dElem.clientWidth + "," +  dElem.clientHeight + " - "  + w.innerWidth + "," + w.innerHeight);
  228.           
  229.           if (!ctx.isEmbed) {
  230.             curtain = d.createElementNS(HTML_NS, "div");
  231.             with (curtain.style) {
  232.               top = left = "0px";
  233.               
  234.               width = (clientWidth + w.scrollX) + "px";
  235.               height = (clientHeight + w.scrollY) + "px";
  236.     
  237.               padding = margin = borderWidth = MozOutlineWidth = "0px";
  238.               position = "absolute";
  239.               zIndex = "99999999";
  240.               
  241.               background = this.rndColor();
  242.             }
  243.             frameStyle = w.parent.getComputedStyle(frame, '');
  244.           }     
  245.           
  246.           if (curtain && frame) {
  247.             dElem.appendChild(curtain);
  248.           }
  249.           
  250.           var maxWidth = Math.max(Math.min(this.maxWidth, clientWidth * zoom), this.minWidth) / zoom ;
  251.           var maxHeight = Math.max(Math.min(this.maxHeight, clientHeight * zoom), this.minHeight) / zoom;
  252.     
  253.           box = this.getBox(o, d, w);
  254.           
  255.           // expand to parent form if needed
  256.           var form = o.form;
  257.           var formBox = null;
  258.           if (frame && !ctx.isEmbed && (form || (form = this.findParentForm(o)))) {
  259.     
  260.             formBox = this.getBox(form, d, w);
  261.             if (!(formBox.width && formBox.height)) { // some idiots put <form> as first child of <table> :(
  262.               formBox = this.getBox(form.offsetParent || form.parentNode, d, w);
  263.               if (!(formBox.width && formBox.height)) {
  264.                 formBox = this.getBox(form.parentNode.offsetParent || o.offsetParent, d, w);
  265.               }
  266.             }
  267.       
  268.             if (formBox.width && formBox.height) {
  269.               ctx.x = ctx.x || box.x + box.width;
  270.               ctx.y = ctx.y || box.y + box.height;
  271.               box = formBox;
  272.               var delta;
  273.               if (box.x < 0) {
  274.                 box.screenX -= box.x * zoom;
  275.                 box.x = 0;
  276.               }
  277.               if (box.y < 0) {
  278.                 box.screenY -= box.y * zoom;
  279.                 box.y = 0;
  280.               }
  281.               if (box.x + Math.min(box.width, maxWidth) < ctx.x) {
  282.                 box.width = Math.min(box.width, maxWidth);
  283.                 delta = ctx.x + 4 - box.width - box.x;
  284.                 box.x += delta;
  285.                 box.screenX += delta * zoom;
  286.                
  287.               }
  288.               if (box.y + Math.min(box.height, maxHeight) < ctx.y) {
  289.                 box.height = Math.min(box.height, maxHeight);
  290.                 delta = ctx.y + 4 - box.height - box.y;
  291.                 box.y += delta;
  292.                 box.screenY += delta * zoom;
  293.               }
  294.               o = form;
  295.             }
  296.           }
  297.     
  298.           bgStyle = dElem.style.background;
  299.           dElem.style.background = bg;
  300.           
  301.           // clip, slide in viewport and trim
  302.           
  303.           var vp = { 
  304.             x: w.scrollX, 
  305.             y: w.scrollY, 
  306.             width: Math.max(w.innerWidth - sd.w, 32), 
  307.             height: Math.max(w.innerHeight - sd.h, 32),
  308.             frame: frame
  309.           };
  310.   
  311.           if (ctx.isEmbed) { // check in-page vieport
  312.             vp.frame = null;
  313.             vp.x = Math.max(vp.x, box.x);
  314.             vp.y = Math.max(vp.y, box.y);
  315.             vp.width = Math.min(vp.width, box.width);
  316.             vp.height = Math.min(vp.height, box.height);
  317.             
  318.             for(form = o; form = form.parentNode;) {
  319.     
  320.               if ((form.offsetWidth < box.width || form.offsetHeight < box.height) &&
  321.                   w.getComputedStyle(form, '').overflow != "visible") {
  322.                 
  323.                 // check if we're being fooled by some super-zoomed applet
  324.                 if (box.width / 4 <= form.offsetWidth && box.height / 4 <= form.offsetHeight) {
  325.                   formBox = this.getBox(form, d, w);
  326.                   
  327.                   if (box.x < formBox.x) {
  328.                     box.x = formBox.x;
  329.                     box.screenX = formBox.screenX;
  330.                   }
  331.                   if (box.y < formBox.y) { 
  332.                     box.y = formBox.y;
  333.                     box.screenY = formBox.screenY;
  334.                   }
  335.                   if (box.width + box.x > formBox.width + formBox.x) box.width = Math.max(this.minWidth, form.clientWidth - (box.x - formBox.x));
  336.                   if (box.height + box.y > formBox.height + formBox.y) box.height = Math.max(this.minHeight, form.offsetHeight - (box.y - formBox.y));
  337.                 }
  338.                 break;
  339.               }
  340.             }
  341.           } else if (!(sd.w || sd.h)) { // no scrollbars
  342.             if (!sd.w) {
  343.               vp.x = 0;
  344.               vp.width = curtain.offsetWidth;
  345.             }
  346.             if (!sd.h) {
  347.               vp.y = 0;
  348.               vp.height = curtain.offsetHeight;
  349.             }
  350.           }
  351.           
  352.           box.oX = box.x;
  353.           box.oY = box.y;
  354.           box.oW = box.width;
  355.           box.oH = box.height;
  356.           
  357.           // print("Fitting " + box.toSource() + " in " + vp.toSource() + " - zoom: " + zoom + " - ctx " + ctx.x + ", " + ctx.y + " - max " + maxWidth + ", " + maxHeight);
  358.     
  359.           this._constrain(box, "x", "width", maxWidth, vp, ctx.x, zoom);
  360.           this._constrain(box, "y", "height", maxHeight, vp, ctx.y, zoom);
  361.           // print(box.toSource());     
  362.           
  363.           c.width = box.width;
  364.           c.height = box.height;
  365.           
  366.           
  367.           if (this.ns.consoleDump & LOG_CLEARCLICK) this.ns.dump("Snapshot at " + box.toSource() + " + " + w.pageXOffset + ", " + w.pageYOffset);
  368.           
  369.           
  370.           
  371.           img1 = snapshot(w, box.x, box.y);
  372.         
  373.         } finally {
  374.           docPatcher.clean(false);
  375.         }
  376.       
  377.   
  378.         var rootElement = top.document.documentElement;
  379.         var rootBox = this.getBox(rootElement, top.document, top);
  380.         
  381.         var offsetX = (box.screenX - rootBox.screenX) / zoom;
  382.         var offsetY = (box.screenY - rootBox.screenY) / zoom;
  383.         var ret = true;
  384.         var tmpImg;
  385.         
  386.         const offs = ctx.isEmbed ? [0] : [0, -1, 1, -2, 2, -3, -3];
  387.   
  388.         checkImage:
  389.         for each(var x in offs) {
  390.           for each(var y in offs) {
  391.             tmpImg = snapshot(top, offsetX + x * zoom, offsetY + y * zoom);
  392.             if (img1 == tmpImg) {
  393.               ret = false;
  394.               break checkImage;
  395.             }
  396.             if (!img2) img2 = tmpImg;
  397.           }
  398.         }
  399.         
  400.         if (ret && !curtain && ctx.isEmbed) {
  401.           curtain = d.createElementNS(HTML_NS, "div");
  402.           if (docPatcher) curtain.className = docPatcher.shownCS;
  403.           with (curtain.style) {
  404.             // we expand by 1 pixel in order to avoid antialias effects on the edge at zoom != 1 (GMail Flash attachment)
  405.             top = (o.offsetTop - 1) + "px";
  406.             left = (o.offsetLeft -1) + "px";
  407.             width = (o.offsetWidth +2) + "px";
  408.             height = (o.offsetHeight +2) + "px";
  409.             position = "absolute";
  410.             zIndex = w.getComputedStyle(o, '').zIndex;
  411.             background = this.rndColor();
  412.           }
  413.           
  414.           if (o.nextSibling) {
  415.             o.parentNode.insertBefore(curtain, o.nextSibling);
  416.           } else {
  417.             o.parentNode.appendChild(curtain);
  418.           }
  419.           
  420.           ret = snapshots(box.x, box.y, offsetX, offsetY);
  421.         }
  422.         
  423.         if (ret && ctx.isEmbed && ("x" in ctx) && c.width > this.minWidth && c.height > this.minHeight) {
  424.           c.width = this.minWidth;
  425.           c.height = this.minHeight;
  426.           for each(x in [Math.max(ctx.x - this.minWidth, box.oX), Math.min(ctx.x, box.oX + box.oW - this.minWidth)]) {
  427.             for each(y in [Math.max(ctx.y - this.minHeight, box.oY), Math.min(ctx.y, box.oY + box.oH - this.minHeight)]) {
  428.               ret = snapshots(x, y, offsetX + (x - box.x), offsetY + (y - box.y));
  429.               if (!ret) {
  430.                 offsetX += (x - box.x);
  431.                 offsetY += (y - box.y);
  432.                 box.x = x;
  433.                 box.y = y;
  434.                 break;
  435.               }
  436.             }
  437.             if (!ret) break;
  438.           }
  439.         }
  440.         
  441.         if (ctx.debug) {
  442.           ret = true;
  443.           img2 = tmpImg;
  444.         }
  445.         
  446.         if (ret) {
  447.           
  448.           if (curtain) {
  449.   
  450.             if (ctx.debug) {
  451.               
  452.               if (docPatcher.cleanSheet) {
  453.                 curtain.id = "curtain_" + DOM.rndId();
  454.                 docPatcher.cleanSheet += " #" + curtain.id + " { opacity: .4 !important }";
  455.               }
  456.               
  457.               curtain.style.opacity = ".4"
  458.               
  459.             } else {
  460.               curtain.parentNode.removeChild(curtain);
  461.             }
  462.             snapshots(box.x, box.y, offsetX, offsetY);
  463.           }
  464.           
  465.           ctx.img =
  466.           {
  467.             src: img1,
  468.             altSrc: img2,
  469.             width: c.width,
  470.             height: c.height
  471.           }
  472.         }
  473.       
  474.       } finally {
  475.         if (ctx.isEmbed) docPatcher.blankPositioned(false);
  476.         
  477.         if (curtain && curtain.parentNode) curtain.parentNode.removeChild(curtain);
  478.         if (typeof(bgStyle) == "string") dElem.style.background = bgStyle;
  479.        
  480.         docPatcher.opaque(false);
  481.         docPatcher.linkAlertHack(false);
  482.         docPatcher.fbPresenceHack(false);
  483.         
  484.         if (objClass) objClass.reset();
  485.         if (frameClass) frameClass.reset();
  486.         if (viewer) viewer.enableRendering = true;
  487.       }
  488.       
  489.       return ret;
  490.    
  491.     }  
  492.   };
  493.  
  494.   for (var p in ClearClickHandlerLegacy) {
  495.     ClearClickHandler.prototype[p] = ClearClickHandlerLegacy[p];
  496.   }
  497.  
  498. })()
  499.